/*
*********************************************************************************************************
*
*	模块名称 : USART调试串口驱动模块
*	文件名称 : bsp_usart.c
*	版    本 : V1.0
*	说    明 : 调试串口重定向
*
*	修改记录 :
*		版本号  日期        作者     说明
*		V1.0    2024-12-06 astronG  正式发布
*
*	Copyright (C), 2015-2030, astronG
*
*********************************************************************************************************
*/

#include "bsp.h"
#include "usart.h"

// 假设ICM - 20948的7位地址是0x68
#define ICM20948_ADDRESS (0x68 << 1)  
// 加速度计数据起始寄存器地址
#define ACCEL_DATA_REG 0x3B

uint16_t dma_last_pos = 0;
//static volatile uint16_t dma_current_pos = 0;
uint16_t dma_current_pos = 0;
uint8_t uart_rx_buffer[UART_RX_BUFFER_SIZE];


/*
*********************************************************************************************************
*	函 数 名: debug_print
*	功能说明: 格式化并通过UART发送调试信息。该函数接受一个格式化字符串和可变数量的参数，
*            将它们格式化为一个字符串，然后通过UART发送出去。
*	形    参：
*           fmt: 格式化字符串，类似于printf的格式。
*           ...: 可变数量的参数，与fmt中的格式说明符对应。
*	返 回 值: 无
* 注意事项：传入参数不要超过255个字节，否则会导致数据丢失。
*						本函数进行了线程安全保护。(不要在中断调用本函数)
*********************************************************************************************************
*/
void debug_print(const char *const fmt, ...)
{
    char str[256];
    uint16_t len;
    va_list args;
    memset(str, 0, sizeof(str));
    va_start(args, fmt);
    vsnprintf(str, 255, fmt, args);
    va_end(args);
    len = strlen(str);
    // 获取互斥锁，保护串口资源
    xSemaphoreTake(xUartMutex, portMAX_DELAY);
    HAL_UART_Transmit_DMA(&huart1, (uint8_t *)str, len);
    // 等待发送完成信号量
    xSemaphoreTake(xTxSemaphore, portMAX_DELAY);
    // 释放互斥锁
    xSemaphoreGive(xUartMutex);
    //    if(xSemaphoreTake(xUartMutex, pdMS_TO_TICKS(100))) {
    //        // 等待DMA空闲
    //        if(xSemaphoreTake(xTxSemaphore, pdMS_TO_TICKS(100))) {
    //            HAL_UART_Transmit_DMA(&huart1, (uint8_t*)str, len);
    //        } else {
    //            // 超时处理
    //        }
    //        xSemaphoreGive(xUartMutex);
    //    }
}

/*
*********************************************************************************************************
*	函 数 名: HAL_UART_TxCpltCallback
*	功能说明: UART发送完成回调函数
*	形    参：
*           huart: UART句柄
*	返 回 值: 无
*********************************************************************************************************
*/
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
    if (huart->Instance == USART1) {
        BaseType_t xHigherPriorityTaskWoken = pdFALSE;
        // 释放发送完成信号量
        xSemaphoreGiveFromISR(xTxSemaphore, &xHigherPriorityTaskWoken);
        portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
    }
}



/*
*********************************************************************************************************
*	函 数 名: UART_IdleHandler
*	功能说明: 串口空闲中断处理函数
*	形    参: huart - 串口句柄
*	返 回 值: 无
*********************************************************************************************************
*/
void UART_IdleHandler(UART_HandleTypeDef *huart)
{
    if (huart->Instance == USART1) {
        __HAL_UART_CLEAR_IDLEFLAG(huart); // 清除空闲中断标志
        // 记录当前DMA位置
        dma_current_pos = UART_RX_BUFFER_SIZE - __HAL_DMA_GET_COUNTER(huart->hdmarx);
        // 释放信号量通知任务有数据到达
        xSemaphoreGiveFromISR(xUartRxSemaphore, NULL);
    }
}

/*
*********************************************************************************************************
*	函 数 名: ProcessUartData
*	功能说明: 处理接收到的串口数据，检测帧头帧尾
*	形    参: start_index - 数据起始索引
*           length - 数据长度
*	返 回 值: 无
*********************************************************************************************************
*/
void ProcessUartData(uint16_t start_index, uint16_t length)
{
    static uint8_t frame_state = 0;
    static uint16_t frame_length = 0;
    static UartFrame frame;  // 静态帧结构体
		
    for (uint16_t i = 0; i < length; i++) {
        uint16_t buffer_index = (start_index + i) % UART_RX_BUFFER_SIZE;
        uint8_t data_byte = uart_rx_buffer[buffer_index];

        // 检查缓冲区溢出
        if (frame_length >= UART_MAX_FRAME_SIZE) {
            frame_state = 0;
            frame_length = 0;
            memset(&frame, 0, sizeof(UartFrame));
            continue;
        }

        // 存储所有字节（包括帧头和帧尾）
        frame.data[frame_length++] = data_byte;

        // 状态机处理
        switch (frame_state) {
        case 0:
            if (data_byte == 0x55) {
                frame_state = 1;
            }

            break;

        case 1:
            frame_state = (data_byte == 0xAA) ? 2 : 0;
            break;

        case 2:
            frame_state = (data_byte == 0x55) ? 3 : 0;
            break;

        case 3:
            frame_state = (data_byte == 0xAA) ? 4 : 0;
            break;

        case 4:
            if (data_byte == 0x16) { frame_state = 5;
            }

            break;

        case 5:
            frame_state = (data_byte == 0xE9) ? 6 : 4;
            break;

        case 6:
            frame_state = (data_byte == 0x16) ? 7 : 4;
            break;

				case 7:
        if (data_byte == 0xE9) {
            // 完整帧接收完成
            frame.length = frame_length;
						
            // 将帧发送到队列
            if (xQueueSend(xUartFrameQueue, &frame, 0) != pdTRUE) {
                debug_print("Frame queue full, frame discarded\r\n");
            }

            frame_state = 0;
            frame_length = 0;
            memset(&frame, 0, sizeof(UartFrame));
        } else {
            frame_state = 4;  // 回到数据状态
        }
        break;

        default:
            frame_state = 0;
            frame_length = 0;
            memset(&frame, 0, sizeof(UartFrame));
            break;
        }

        // 状态错误时重置
        if (frame_state == 0 && frame_length > 0) {
            frame_length = 0;
            memset(&frame, 0, sizeof(UartFrame));
        }
    }
}

/*
*********************************************************************************************************
*	函 数 名: ProcessUartFrame
*	功能说明: 处理完整的串口帧
*	形    参: frame - 帧数据
*	返 回 值: 无
*********************************************************************************************************
*/
void ProcessUartFrame(UartFrame *frame)
{
    // 直接提取指令部分（帧头帧尾已确认正确）
    uint8_t address = frame->data[4];  // 第5字节：指令类型
    uint8_t subcmd = frame->data[5];   // 第6字节：子指令
    uint16_t data1 = (frame->data[6] << 8) | frame->data[7]; // 第7-8字节：数据
    
    UartFrame response;
		uint8_t ID;
    // 指令处理
    switch (address) {
    case 0xFF:  // 示例指令
        switch (subcmd) {
        case 0xA1:
						MyI2C_Start();
						MyI2C_SendByte(0xD0);
						ID = MyI2C_ReceiveAck();
						MyI2C_Stop();
//						ID = MPU6050_ReadReg(ICM_WHO_AM_I);		
//						HAL_I2C_Mem_Read(&hi2c1, ICM20948_ADDRESS, 0x00, I2C_MEMADD_SIZE_8BIT, accelData, 6, 100);
//						int16_t accelX = (accelData[1] << 8) | accelData[0];
//						ID = MPU6050_Read_ID();
            // 构建响应帧
            BuildResponseFrame(&response, 0xFF, ID, data1);
            SafeUartTransmit(response.data, response.length);
            break;

        case 0xA2:
            BuildResponseFrame(&response, 0xFF, 0xB2, data1);
            SafeUartTransmit(response.data, response.length);
            break;
            
        default:
            debug_print("Unknown subcmd: %02X\r\n", subcmd);
            break;
        }
        break;

    default:
        debug_print("Unknown address: %02X\r\n", address);
        break;
    }
}


void SafeUartTransmit(uint8_t *data, uint16_t length)
{
    if (xSemaphoreTake(xUartMutex, pdMS_TO_TICKS(50))) {
        //        if(xSemaphoreTake(xTxSemaphore, pdMS_TO_TICKS(50)) == pdTRUE) {
        //            HAL_UART_Transmit_DMA(&huart1, data, length);
        //        }
        HAL_UART_Transmit_DMA(&huart1, data, length);
        xSemaphoreGive(xUartMutex);
    }
}

// 辅助函数：构建响应帧
void BuildResponseFrame(UartFrame *response, uint8_t addr, uint8_t cmd, uint16_t data)
{
    response->data[0] = 0x55;  // FRAME_HEADER_1
    response->data[1] = 0xAA;  // FRAME_HEADER_2  
    response->data[2] = 0x55;  // FRAME_HEADER_3
    response->data[3] = 0xAA;  // FRAME_HEADER_4
    response->data[4] = addr;  // 地址
    response->data[5] = cmd;   // 命令
    response->data[6] = data >> 8;    // 数据高字节
    response->data[7] = data & 0xFF;  // 数据低字节
    response->data[8] = 0x16;  // FRAME_FOOTER_1
    response->data[9] = 0xE9;  // FRAME_FOOTER_2
    response->data[10] = 0x16; // FRAME_FOOTER_3
    response->data[11] = 0xE9; // FRAME_FOOTER_4
    response->length = 12;
}
